import socket
import json
import threading
import time
import requests
import logging
from datetime import datetime

# 配置日志，添加日期时间格式
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s.%(msecs)03d - %(levelname)s - %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)

class APIClient:
    """API客户端，封装HTTP接口调用"""
    
    def __init__(self, host, face_port=6688, tts_port=8866):
        self.host = host
        self.face_port = face_port
        self.tts_port = tts_port
        self.face_base_url = f"http://{host}:{face_port}"
        self.tts_base_url = f"http://{host}:{tts_port}"
    
    def send_request(self, base_url, path, data):
        """发送HTTP请求并返回响应"""
        url = f"{base_url}{path}"
        headers = {"Content-Type": "application/json"}
        
        try:
            logging.info(f"发送请求: {url} - {json.dumps(data)}")
            response = requests.post(url, json=data, timeout=30)
            logging.debug(f"原始响应: {response.text}")
            
            try:
                response_data = response.json()
                logging.info(f"解析响应: {response_data}")
                return response_data
            except json.JSONDecodeError:
                logging.error(f"无效JSON响应: {response.text}")
                return {"code": response.status_code, "message": response.text, "success": False}
                
        except requests.exceptions.Timeout:
            logging.error("请求超时（30秒）")
            return {"status": "error", "errorCode": "TIMEOUT"}
        except Exception as e:
            logging.error(f"请求失败: {e}")
            return {"status": "error", "errorCode": str(e)}
    
    # 人脸识别接口
    def start_face_recognition(self):
        return self.send_request(self.face_base_url, "/api/faceRecognition", {"action": "start_recognition"})
    
    def stop_face_recognition(self):
        return self.send_request(self.face_base_url, "/api/faceRecognition", {"action": "stop_recognition"})
    
    def query_recognition(self, user_id_type="1"):
        return self.send_request(self.face_base_url, "/api/faceRecognition", 
                               {"action": "query_recognition", "userIdType": user_id_type})
    
    def query_face_info(self, user_id, user_id_type="1"):
        return self.send_request(self.face_base_url, "/api/faceRecognition", 
                               {"action": "query_faceInfo", "userId": user_id, "userIdType": user_id_type})
    
    def subscribe_face_events(self, event_types):
        return self.send_request(self.face_base_url, "/api/faceEvent", 
                               {"action": "subscribe", "eventTypes": event_types})
    
    def unsubscribe_face_events(self, event_types):
        return self.send_request(self.face_base_url, "/api/faceEvent", 
                               {"action": "unsubscribe", "eventTypes": event_types})
    
    # 语音合成接口
    def add_tts_message(self, message):
        """添加语音到队列"""
        return self.send_request(self.tts_base_url, "/api/tts", {"action": "add", "message": message})
    
    def flush_tts_queue(self):
        """清空语音队列"""
        return self.send_request(self.tts_base_url, "/api/tts", {"action": "flush"})
    
    def stop_speech(self):
        """停止当前语音"""
        return self.send_request(self.tts_base_url, "/api/tts", {"action": "stop"})
    
    def restart_speech(self, message):
        """重新播报语音（清空队列+播放新内容）"""
        return self.send_request(self.tts_base_url, "/api/tts", {"action": "restart", "message": message})
    
    def query_tts_status(self):
        """查询队列状态"""
        return self.send_request(self.tts_base_url, "/api/tts", {"action": "query_queue_status"})
    
    def subscribe_tts_events(self, event_types):
        """订阅语音事件"""
        return self.send_request(self.tts_base_url, "/api/ttsEvent", 
                               {"action": "subscribe", "eventTypes": event_types})
    
    def unsubscribe_tts_events(self, event_types):
        """取消订阅语音事件"""
        return self.send_request(self.tts_base_url, "/api/ttsEvent", 
                               {"action": "unsubscribe", "eventTypes": event_types})

class TCPClient:
    """TCP客户端，接收服务器事件"""
    
    def __init__(self, host, port, event_handler=None):
        self.host = host
        self.port = port
        self.client_socket = None
        self.running = False
        self.event_handler = event_handler
        self.thread = None
    
    def connect(self):
        """连接到TCP服务器"""
        try:
            self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.client_socket.connect((self.host, self.port))
            self.running = True
            
            # 启动接收线程
            self.thread = threading.Thread(target=self._receive_data)
            self.thread.daemon = True
            self.thread.start()
            
            logging.info(f"已连接到TCP服务器 {self.host}:{self.port}")
            return True
        except Exception as e:
            logging.error(f"连接TCP服务器失败: {e}")
            return False
    
    def disconnect(self):
        """断开与服务器的连接"""
        self.running = False
        if self.client_socket:
            self.client_socket.close()
            self.client_socket = None
        logging.info("已断开与TCP服务器的连接")
    
    def _receive_data(self):
        """接收服务器数据"""
        buffer = ""
        try:
            while self.running:
                try:
                    data = self.client_socket.recv(1024).decode('utf-8')
                    if not data:
                        logging.warning("服务器关闭了连接")
                        self.running = False
                        break
                    
                    buffer += data
                    
                    # 处理所有完整的消息（以\r\n结尾）
                    while '\r\n' in buffer:
                        message, buffer = buffer.split('\r\n', 1)
                        try:
                            event = json.loads(message)
                            if self.event_handler:
                                self.event_handler(event)
                            else:
                                logging.info(f"收到事件: {event}")
                        except json.JSONDecodeError:
                            logging.error(f"无效的JSON消息: {message}")
                            
                except socket.timeout:
                    continue
                except Exception as e:
                    if self.running:
                        logging.error(f"接收数据时出错: {e}")
                    break
        finally:
            self.disconnect()

class ProtocolTester:
    """协议测试器"""
    
    def __init__(self, host="localhost"):
        self.host = host
        self.api_client = APIClient(host)
        self.tcp_client = TCPClient(host, 6667, self._handle_event)
        self.face_events_received = 0
        self.tts_events_received = 0
    
    def _handle_event(self, event):
        """处理接收到的事件"""
        event_type = event.get("eventType")
        data = event.get("data")
        
        logging.info(f"接收到事件: {event_type} - {data}")
        
        if event_type == "FACE_RECOGNIZED":
            self.face_events_received += 1
        elif event_type == "SPEECH_STATUS_CHANGED":
            self.tts_events_received += 1
    
    def run_all_tests(self):
        """运行所有测试"""
        
        results = {
            "TCP连接": self.test_tcp_connection(),
            "人脸识别接口": self.test_face_api(),
            "语音合成接口": self.test_tts_api(),
            "事件订阅": self.test_event_subscription()
        }
        
        # 打印最终测试结果
        print("\n===== 最终测试结果 =====")
        for test_name, result in results.items():
            status = "通过" if result.get("success") else "失败"
            print(f"{test_name}: {status}")
            print(f"  详情: {result.get('message')}")
        
        return results
    
    def test_tcp_connection(self):
        """测试TCP连接"""
        try:
            logging.info("开始测试TCP连接...")
            
            # 连接TCP服务器
            success = self.tcp_client.connect()
            if not success:
                return {"success": False, "message": "无法连接到TCP服务器"}
            
            # 等待心跳包
            start_time = time.time()
            while time.time() - start_time < 15:  # 最多等待15秒
                if self.face_events_received > 0 or self.tts_events_received > 0:
                    break
                time.sleep(1)
            
            # 断开连接
            self.tcp_client.disconnect()
            
            return {"success": True, "message": "TCP连接测试通过"}
        except Exception as e:
            return {"success": False, "message": f"TCP连接测试失败: {str(e)}"}
    
    def test_face_api(self):
        """测试人脸识别API"""
        try:
            logging.info("开始测试人脸识别API...")
            
            # 启动识别
            start_resp = self.api_client.start_face_recognition()
            if not start_resp.get("success"):
                return {"success": False, "message": f"启动识别失败: {start_resp.get('message')}"}
            
            # 查询识别结果
            query_resp = self.api_client.query_recognition()
            if not query_resp.get("success"):
                return {"success": False, "message": f"查询识别结果失败: {query_resp.get('message')}"}
            
            # 查询人脸信息
            face_info_resp = self.api_client.query_face_info("12345")
            if not face_info_resp.get("success"):
                return {"success": False, "message": f"查询人脸信息失败: {face_info_resp.get('message')}"}
            
            # 停止识别
            stop_resp = self.api_client.stop_face_recognition()
            if not stop_resp.get("success"):
                return {"success": False, "message": f"停止识别失败: {stop_resp.get('message')}"}
            
            return {"success": True, "message": "人脸识别API测试通过"}
        except Exception as e:
            return {"success": False, "message": f"人脸识别API测试失败: {str(e)}"}
    
    def test_tts_api(self):
        """测试语音合成API"""
        try:
            logging.info("开始测试语音合成API...")
            
            # 清空队列
            self.api_client.flush_tts_queue()
            
            # 添加语音到队列
            add_resp = self.api_client.add_tts_message("原始语音内容")
            if not add_resp.get("success"):
                return {"success": False, "message": f"添加语音失败: {add_resp.get('message')}"}
            
            # 查询队列状态
            status_resp = self.api_client.query_tts_status()
            if not status_resp.get("success"):
                return {"success": False, "message": f"查询队列状态失败: {status_resp.get('message')}"}
            
            # 停止当前语音
            stop_resp = self.api_client.stop_speech()
            if not stop_resp.get("success"):
                return {"success": False, "message": f"停止语音失败: {stop_resp.get('message')}"}
            
            # 重新播报语音
            restart_resp = self.api_client.restart_speech("重新播报的语音内容")
            if not restart_resp.get("success"):
                return {"success": False, "message": f"重新播报语音失败: {restart_resp.get('message')}"}
            
            return {"success": True, "message": "语音合成API测试通过"}
        except Exception as e:
            return {"success": False, "message": f"语音合成API测试失败: {str(e)}"}
    
    def test_event_subscription(self):
        """测试事件订阅功能"""
        try:
            logging.info("开始测试事件订阅功能...")
            
            # 重新连接TCP客户端
            self.tcp_client.connect()
            
            # 订阅人脸事件
            face_sub_resp = self.api_client.subscribe_face_events(["FACE_RECOGNIZED"])
            if not face_sub_resp.get("success"):
                return {"success": False, "message": f"订阅人脸事件失败: {face_sub_resp.get('message')}"}
            
            # 订阅语音事件
            tts_sub_resp = self.api_client.subscribe_tts_events(["SPEECH_STATUS_CHANGED"])
            if not tts_sub_resp.get("success"):
                return {"success": False, "message": f"订阅语音事件失败: {tts_sub_resp.get('message')}"}
            
            # 启动人脸识别
            self.api_client.start_face_recognition()
            
            # 添加语音到队列
            self.api_client.add_tts_message("测试事件订阅")
            
            # 等待事件接收
            start_time = time.time()
            while time.time() - start_time < 20:  # 最多等待20秒
                if self.face_events_received >= 1 and self.tts_events_received >= 1:
                    break
                time.sleep(1)
            
            # 取消订阅
            self.api_client.unsubscribe_face_events(["FACE_RECOGNIZED"])
            self.api_client.unsubscribe_tts_events(["SPEECH_STATUS_CHANGED"])
            
            # 停止人脸识别
            self.api_client.stop_face_recognition()
            
            # 断开TCP连接
            self.tcp_client.disconnect()
            
            # 检查是否收到了足够的事件
            if self.face_events_received >= 1 and self.tts_events_received >= 1:
                return {"success": True, "message": "事件订阅测试通过"}
            else:
                return {"success": False, "message": f"收到的事件不足: 人脸事件({self.face_events_received})，语音事件({self.tts_events_received})"}
                
        except Exception as e:
            return {"success": False, "message": f"事件订阅测试失败: {str(e)}"}

if __name__ == "__main__":
    logging.info("开始测试协议V1.5，目标主机: localhost")
    logging.info("==================================================")
    
    tester = ProtocolTester()
    tester.run_all_tests()    
